//how to commit SVN:
//right click RAMbots founder then select SVN commit select files to update
#include "CreateEnv.h"	
#include "Utilities.h"
#include "TexturedObj.h"
#include "Agent.h"
#include "User.h"
#include "NonUser.h"
#include "PathTraverser.h"
#include "Pathfinder.h"
#include "Grid.h"
#include "PointLight.h"
#include "Robot.h"
#include "Hostile.h"
#include "Hostage.h"
#include "Camera.h"
#include "RadioButton.h"

#include <iostream>

using namespace std;

////////////////////////////////////////////////////////////////////////////////////////
// Defined in Main.cpp
extern NonUser world3D;		//list for holding non user controlled 3D objects in world
extern User user;			//list for holding user controlled 3D objects in world
extern vector<Robot *> myRobots;
extern vector<Hostile *> myHostiles;
extern vector<Hostage *> myHostages;
extern Camera * mainCamera;
extern list<Camera *> cameras;
extern list<RadioButton *> pcAgentButtons;
extern Agent * commander;
extern Agent * activeAgent;
extern void selectAgent();				// button click handler



Grid<char> occupancy = Grid<char>( 22, 50, true );
Grid<char> wayPointMap = Grid<char>( 22, 50, ' ' );
Grid<char> routingTable = Grid<char>( 21, 21, ' ' );
vector<Triple> wayPointPositions = vector<Triple>( 21, ' ' );

// Set up A* pathfinding
extern Pathfinder goGetEm;

void 
Environment::useDefaultEnv()
{ 
	// create mini map
	dbCreateBitmap ( 10, 172, 400 );

	////////////////////////////////////////////////////////////////////////////////////
	// Load all of the textures
	dbLoadImage			("Models\\floor3.jpg" , 1 , 0 );
	dbLoadImage			("Models\\GI\\Gi.dds" , 2 );
	dbLoadImage			("Models\\shadow.png" , 3 , 0 );
	dbLoadImage			("Models\\wall1.jpg" , 4 , 0 );
	dbLoadImage			("Models\\wall11c.jpg" , 5 , 0 );
	dbLoadImage			("Models\\wall5c.jpg" , 6 , 0 );
	dbLoadImage			("Models\\shadow.jpg" , 7 , 0 );
	dbLoadImage			("Models\\wall1 bump.jpg" , 8 , 0 );
	dbLoadImage			("Models\\wall11c bump.jpg" , 9 , 0 );
	dbLoadImage			("Models\\wall5c bump.jpg" , 10 , 0 );
	dbLoadImage			("Models\\Thug\\thug.dds" , 11 , 0 );
	dbLoadImage			("Models\\crosshair.png" , 12 , 1 );
	dbLoadImage			("Models\\blood.png" , 13 , 1 ); // blood on the floor
	dbLoadImage			("Models\\hit.png" , 14 , 1); // blood as a shot hits home
	dbLoadImage			("Models\\fire.png" , 15 , 1); // fireball from the running monsters
	dbLoadImage			("Models\\laser.png" , 16 , 1); // laserball from the troopers
	dbLoadImage			("Models\\title.jpg" , 17 , 1); // laserball from the troopers

	// added new wall textures
	dbLoadImage			("Models\\metal\\zaun_a.jpg" , 20 , 1);
	dbLoadImage			("Models\\metal\\zaun_tex.jpg" , 21 , 1);
	dbLoadImage			("Models\\wall\\brick01.jpg" , 22 , 1);
	dbLoadImage			("Models\\wall\\wall01.jpg" , 23 , 1);
	dbLoadImage			("Models\\wall\\wall04.jpg" , 24 , 1);


	/////////////////////////////////////////////////////////////////////////////////////
	dbLoadSound			( "Models\\shoop.wav" , 3 , 0 );
	dbLoadSound			( "Models\\shoop.wav" , 4 , 0 );

	objectCount = 3000;
	charNum		= 0;
	stringNum	= 0;
	cWayPoint	= 0;
	addFloor	= 0;
	lightNum	= 1; // can have 6 lights max in the level R, G or B
	shadow		= 0;
	doorSound		= false;
	doorCount		= 0;
	int newID		= 1;
	visCount		= 0;
	currentVis		= 0;
	int currCamera	= 1;
	int viewWidth	= 160;
	int viewHeight	= 120;
	int startX		= 35;
	int startY		= 593;
	//int startY		= 200;
	int shiftX		= 260;
	int currButton = 1;

	// Setup pathfinding
	goGetEm = Pathfinder::Pathfinder( & occupancy, 100, Pathfinder::AStar, Pathfinder::Euclidean, Pathfinder::Depth, 1000, true, 15, 15 );

	// Store waypoint info
	goGetEm.loadWaypoints( & wayPointMap, & routingTable, & wayPointPositions );

	cameras.clear();


	// Define the level

	czLevel[0]	= "{121                  ";
	czLevel[1]	= " 1$1                  ";
	czLevel[2]	= " 1.1                  ";
	czLevel[3]	= " 1.1                 }";		// create empty room for testing.
	czLevel[4]	= "{1.222222222222222221 ";
	czLevel[5]	= " 1~..^@...$....*h...1 ";		// "assault trooper" is next to box... baddie is alone
	czLevel[6]	= " 1......R...R.......1 ";		// player start is in middle (facing down at ground in FP view).
	czLevel[7]	= " 1........R.........1 ";		// robot is wherever you see 'R'.
	czLevel[8]	= " 1.......x..........1 ";
	czLevel[9]	= " 1..................1 ";		// baddie id			= 9		key: *
	czLevel[10]	= " 1...........22#22221 ";		// assault trooper id	= 8		key: @
	czLevel[11]	= " 1..........22.ng...1 ";		// robot				= 4		key: R
	czLevel[12]	= " 1.........22..s....1 ";		// hostages				= 7		key: h
	czLevel[13]	= " 12222222222222#22221}";
	czLevel[14] = "{           122#221   ";
	czLevel[15] = "            1#####1   ";
	czLevel[16] = "            1#222#1  }";
	czLevel[17] = "{122222222222#222#221 ";
	czLevel[18] = " 1...........n...n..1 ";
	czLevel[19] = " 1........x.........1 ";
	czLevel[20] = " 1..........b.......1 ";
	czLevel[21] = " 1..@s..@.....^..^..1 ";
	czLevel[22] = " 1222#222222222222221}";
	czLevel[23] = "{   1#221             ";
	czLevel[24] = "    1###1             ";
	czLevel[25] = "    122#1            }";
	czLevel[26] = "{122222#222221        ";
	czLevel[27] = " 1.....n.....1        ";
	czLevel[28] = " 1...........1        ";
	czLevel[29] = " 1..........^1        ";
	czLevel[30] = " 1.....xr....1        ";
	czLevel[31] = " 1^..........1        ";
	czLevel[32] = " 1...........1        ";
	czLevel[33] = " 1..s.*s.*s..1        ";
	czLevel[34] = " 122#22#22#221       }";
	czLevel[35] = "{  1#22#22#221        ";
	czLevel[36] = "   1#########1        ";
	czLevel[37] = "   122222222#1       }";
	czLevel[38] = "{12222222222#22222221 ";
	czLevel[39] = " 1..........n...^...1 ";
	czLevel[40] = " 1..................1 ";
	czLevel[41] = " 1..................1 ";
	czLevel[42] = " 1....g.............1 ";
	czLevel[43] = " 1........x.........1 ";
	czLevel[44] = " 1..................1 ";
	czLevel[45] = " 1........@.......@.1 ";
	czLevel[46] = " 1..@..........r.*..1 ";
	czLevel[47] = " 1......*...........1 ";
	czLevel[48] = " 1.....^.......^....1 ";
	czLevel[49] = " 12222222222222222221}";

	// #'s are just for wall visibility - don't do anything
	// letters correspond to the closest visible waypoint;
	// capital letters are the waypoints.
	cWayPointMap[0]	= "{###                  ";
	cWayPointMap[1]	= " #a#                  ";
	cWayPointMap[2]	= " #a#                  ";
	cWayPointMap[3]	= " #a#                 }";
	cWayPointMap[4]	= "{#a################## ";
	cWayPointMap[5]	= " #Aaabbbbbbbbbbbbbcc# ";
	cWayPointMap[6]	= " #aabbbbbbbbbbbbbccc# ";
	cWayPointMap[7]	= " #abbbbbbbbbBbbbcccc# ";
	cWayPointMap[8]	= " #bbbbbbbbbbbbcccccc# ";
	cWayPointMap[9]	= " #bbbbbbbbbbbbcCcccc# ";
	cWayPointMap[10]	= " #bbbbbbbbbbb##d##### ";
	cWayPointMap[11]	= " #bbbbbbbbbb##dddddd# ";
	cWayPointMap[12]	= " #bbbbbbbbb##ddDdddd# ";
	cWayPointMap[13]	= " ##############d#####}";
	cWayPointMap[14] = "{           ###e###   ";
	cWayPointMap[15] = "            #FeEeG#   ";
	cWayPointMap[16] = "            #f###g#  }";
	cWayPointMap[17] = "{############h###i### ";
	cWayPointMap[18] = " #jjjjjjhhhhhHhhiIii# ";
	cWayPointMap[19] = " #jjjjjjjhhhhhhhiiii# ";
	cWayPointMap[20] = " #jjjjjjjjhhhhhhiiii# ";
	cWayPointMap[21] = " #jjjJjjjjjhhhhhiiii# ";
	cWayPointMap[22] = " ####j###############}";
	cWayPointMap[23] = "{   #k###             ";
	cWayPointMap[24] = "    #KkL#             ";
	cWayPointMap[25] = "    ###l#            }";
	cWayPointMap[26] = "{######m######        ";
	cWayPointMap[27] = " #mmmmmMmmmmm#        ";
	cWayPointMap[28] = " #mmmmmmmmmmm#        ";
	cWayPointMap[29] = " #mmmmmmmmmmm#        ";
	cWayPointMap[30] = " #nnnnooopppp#        ";
	cWayPointMap[31] = " #nnnnooopppp#        ";
	cWayPointMap[32] = " #nnnnooopppp#        ";
	cWayPointMap[33] = " #nnNnoOopPpp#        ";
	cWayPointMap[34] = " ###n##o##p###       }";
	cWayPointMap[35] = "{  #q##r##s###        ";
	cWayPointMap[36] = "   #QqrRrsStT#        ";
	cWayPointMap[37] = "   #########t#       }";
	cWayPointMap[38] = "{###########u######## ";
	cWayPointMap[39] = " #uuuuuuuuuuUuuuuuuu# ";
	cWayPointMap[40] = " #uuuuuuuuuuuuuuuuuu# ";
	cWayPointMap[41] = " #uuuuuuuuuuuuuuuuuu# ";
	cWayPointMap[42] = " #uuuuuuuuuuuuuuuuuu# ";
	cWayPointMap[43] = " #uuuuuuuuuuuuuuuuuu# ";
	cWayPointMap[44] = " #uuuuuuuuuuuuuuuuuu# ";
	cWayPointMap[45] = " #uuuuuuuuuuuuuuuuuu# ";
	cWayPointMap[46] = " #uuuuuuuuuuuuuuuuuu# ";
	cWayPointMap[47] = " #uuuuuuuuuuuuuuuuuu# ";
	cWayPointMap[48] = " #uuuuuuuuuuuuuuuuuu# ";
	cWayPointMap[49] = " ####################}";

	// used to look up where to go next for a particular destination
	cRoutingTable[0] = " bbbbbbbbbbbbbbbbbbbb"; //A
	cRoutingTable[1] = "a ccccccccccccccccccc"; //B
	cRoutingTable[2] = "ab dddddddddddddddddd"; //C
	cRoutingTable[3] = "ccc eeeeeeeeeeeeeeeee"; //D
	cRoutingTable[4] = "cccd fgfgffffffffffff"; //E
	cRoutingTable[5] = "eeeee ghghhhhhhhhhhhh"; //F
	cRoutingTable[6] = "eeeeef fiiiiiiiiiiiii"; //G
	cRoutingTable[7] = "fffffff ijjjjjjjjjjjj"; //H
	cRoutingTable[8] = "gggggggh jjjjjjjjjjjj"; //I
	cRoutingTable[9] = "hhhhhhhhi kkkkkkkkkkk"; //J
	cRoutingTable[10] = "jjjjjjjjjj llllllllll"; //K
	cRoutingTable[11] = "kkkkkkkkkkk mmommrmmm"; //L
	cRoutingTable[12] = "llllllllllll nopnrppp"; //M
	cRoutingTable[13] = "mmmmmmmmmmmmm opqopqq"; //N
	cRoutingTable[14] = "mmmmmmmmmmmmmn pnrprr"; //O
	cRoutingTable[15] = "mmmmmmmmmmmmmno nosss"; //P
	cRoutingTable[16] = "nnnnnnnnnnnnnnnn rstt"; //Q
	cRoutingTable[17] = "llllllllllllmoooq stt"; //R
	cRoutingTable[18] = "ppppppppppppppppqr tt"; //S
	cRoutingTable[19] = "rrrrrrrrrrrrrqrsqrs u"; //T
	cRoutingTable[20] = "tttttttttttttttttttt "; //U

	cout << "Stored Routing Table" << endl;

	// Copy routing table into grid
	for( stringNum = 0; stringNum < 21; stringNum++ )
	{
		for( charNum = 0; charNum < 21; charNum++ )
		{
			routingTable( stringNum, charNum ) = cRoutingTable[ stringNum ][ charNum ];
		}
	}

	// Handle level decoding
	for ( stringNum = 0 ; stringNum < 50 ; stringNum++ )
	{
		for ( charNum = 0 ; charNum < 22 ; charNum++ )
		{
			shadow = 0;

			// handle storage of waypoint map
			cWayPoint = cWayPointMap[stringNum][charNum];

			// regular navigable square
			if( cWayPoint >= 'a' && cWayPoint <= 'z' )
			{
				wayPointMap( charNum, stringNum ) = cWayPoint;
			}
			// actual waypoints
			else if( cWayPoint >= 'A' && cWayPoint <= 'Z' )
			{
				wayPointPositions[ cWayPoint - 'A' ] = Triple( ( float ) charNum * 100.0f , 0.0f , ( float ) stringNum * 100.0f );
				// convert to lowercase
				wayPointMap( charNum, stringNum ) = cWayPoint - 'A' + 'a';
			}

			// ADD TO MINIMAP FOR EACH CASE


			switch ( czLevel[ stringNum ][ charNum ] )
			{
			case '{':
				{
					vis[visCount].start		= stringNum;
					vis[visCount].startObj	= objectCount;
				} break;
			case '}':
				{
					vis[visCount].end		= stringNum;
					vis[visCount].endObj	= objectCount - 1;
					visCount++;
				} break;
			case '.': // empty space
				{
					occupancy( charNum, stringNum ) = FALSE;
					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case '~': // north facing door empty space 
				{
					occupancy( charNum, stringNum ) = FALSE;

					dbLoadObject			( "Models\\door_frame1.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbYRotateObject			( objectCount , 180 );
					dbScaleObject			( objectCount , 180 , 160 , 130 );
					dbMoveObject			( objectCount ,  -10 );
					dbFadeObject			( objectCount , 200 );
					dbSetObjectCollisionOff	( objectCount );

					door[ doorCount ].type			= 1; // south
					door[ doorCount ].distObj		= ( objectCount );

					objectCount++;

					dbLoadObject			( "Models\\door_1a.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbYRotateObject			( objectCount , 180 );
					dbScaleObject			( objectCount , 100 , 110 , 100 );
					dbMoveObject			( objectCount ,  5 );
					dbSetObjectCollisionOff	( objectCount );

					door[ doorCount ].leftObj		= ( objectCount );
					door[ doorCount ].leftStartX	= dbObjectPositionX ( objectCount );
					door[ doorCount ].leftCurrentX	= dbObjectPositionX ( objectCount );

					objectCount++;

					dbLoadObject			( "Models\\door_1b.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbYRotateObject			( objectCount , 180 );
					dbScaleObject			( objectCount , 100 , 110 , 100 );
					dbMoveObject			( objectCount ,  5 );
					dbSetObjectCollisionOff	( objectCount );

					door[ doorCount ].rightObj		= ( objectCount );
					door[ doorCount ].rightStartX	= dbObjectPositionX ( objectCount );
					door[ doorCount ].rightCurrentX = dbObjectPositionX ( objectCount );

					objectCount++;

					doorCount++;

					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap

					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map

					color = dbRGB ( 255, 255, 255 );//calculate color id for white
					dbInk ( color, color );//set ink color to white
					dbBox ( 8*charNum , 400 - 8*(stringNum), 8*(charNum + 1), 400 - 8 * (stringNum - 1) );
					//draw white representation of door on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case '^': // box
				{
					TexturedObj* obj = new TexturedObj("Models\\Energy-Box.X" , objectCount);
					obj->setPosition(( float ) charNum * 100 , 25 , ( float ) stringNum * 100);
					obj->setScale(400 , 400 , 400);
					//world3D.addObject(objectCount, obj);

					dbSetObjectAmbient		( objectCount , 0 );
					dbSetObjectAmbience		( objectCount , 0x00000000 );
					dbSetObjectSpecular		( objectCount , 0x00111111 );
					objectCount++;
					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 0, 0 );//calculate color id for brown
					dbInk ( color, color );//set ink color to brown
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw brown representation of box on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case '$': // Player start plus empty space
				{
					occupancy( charNum, stringNum ) = FALSE;

					//dbPositionCamera ( 0 , ( float ) charNum * 100.0f , 50.0f , ( float ) stringNum * 100.0f );
					//dbAutomaticCameraCollision	( 0 , 10 , 0 );
					//dbSetCameraRange ( 0 , 1 , 2000 );

					Agent* obj = new Agent("Models\\GI\\H-GI-Idle.x" , newID, goGetEm, occupancy );
					//activeAgent = commander = obj;

					///dbSetShadowShadingOn( newID );
					obj->setPosition(( float ) charNum * 100.0f , 0.0f , ( float ) stringNum * 100.0f);
					obj->setScale(3000.0f , 3000.0f , 3000.0f);
					obj->applyTexture("Models\\GI\\Gi.dds");
					// make sure unit is facing the right direction for later positioning.
					obj->setRotation( 0, 180, 0 );
					dbFixObjectPivot( obj->getID() );

					// Create new camera to follow the commander, placing it in front of
					// the player
					float direction = obj->getRotY();
					Triple camPos = Triple();
					float distance = 20.0f;

					camPos.x = dbNewXValue( obj->getPosX(), direction, distance );
					camPos.y = 50.0f;
					camPos.z = dbNewZValue( obj->getPosZ(), direction, distance );

					Camera * cam = new Camera( currCamera, camPos.x, camPos.y, camPos.z );
					//dbSleep(10);

					cameras.push_back( cam );
					cam->setView( viewWidth, viewHeight, startX + (currCamera - 1) * shiftX, startY );
					//cam->lookAt( obj->getPosX(), obj->getPosY() + 20, obj->getPosZ() );
					cam->setRotation( 0, direction, 0 );
					obj->constrainToRotation( cam, "y" );
					obj->constrainToPosition( cam, "xz" );
					//cam->setToImage( currCamera + 1000, viewWidth, viewHeight );

					// Set main camera to the commander's view
					// UNCOMMENT THIS TO HAVE MAIN CAMERA FOLLOW COMMANDER
/*					mainCamera = new Camera(0, camPos.x, camPos.y, camPos.z );
					mainCamera->setRotation( 0, direction, 0 );
					obj->constrainToRotation( mainCamera, "y" );
					obj->constrainToPosition( mainCamera, "xz" );	*/				

					currCamera++;

					// Create a button so an agent can be selected by clicking on its camera view
					// currButton should be changed to currPlayer to be position-independent
					RadioButton * button = new RadioButton( "Models\\Transparent-Button.png", currButton, 
						startX + (currButton - 1) * shiftX, startY, & selectAgent, viewWidth + 6, viewHeight + 6 );

					pcAgentButtons.push_back( button );
					currButton++;

					// Set animations
					obj->addAnimation( Animation::Attack, "Models\\GI\\H-GI-Attack1.x", 40, true );
					obj->addAnimation( Animation::Die, "Models\\GI\\H-GI-Die.x" );
					obj->addAnimation( Animation::Idle, "Models\\GI\\H-GI-Idle.x", 40, true );
					obj->addAnimation( Animation::Impact, "Models\\GI\\H-GI-Impact.x" );
					obj->addAnimation( Animation::Move, "Models\\GI\\H-GI-Move.x", 120, true );

					user.addUserObject(newID, obj);
					newID++;

					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case 'R': // load robot
				{
					//////////////////////////////////////////////////////////////////////////////////
					// Lecture 7: load and store actions
					Robot* obj = new Robot("Models\\robots\\Android\\H-Android-Static.x" , newID, goGetEm, occupancy );
					obj->setScale(1000.0f , 1000.0f , 1000.0f);
					obj->applyTexture("Models\\robots\\Android\\robot.dds");
					obj->setPosition(( float ) charNum * 100.0f , 0.0f , ( float ) stringNum * 100.0f);

					// enable collision detection
					dbSetObjectCollisionOn ( obj->getID() );

					activeAgent = obj;

					// make sure unit is facing the right direction for later positioning.
					// obj->setRotation( 0, 180, 0 );
					dbYRotateObject( newID, 180.0f );
					dbFixObjectPivot( obj->getID() );

					// leaving this here, to keep offsets in-sync.  TODO: fix this later.
					user.addUserObject(newID, obj);
					myRobots.insert(myRobots.end(), obj);

					// set robot occupancy as occupied.
					occupancy( charNum, stringNum ) = 4;

					// Create new camera to follow this robot, placing it in front of
					// the robot
					float direction = obj->getRotY();
					Triple camPos = Triple();
					float distance = 20.0f;

					camPos.x = dbNewXValue( obj->getPosX(), direction, distance );
					camPos.y = 30.0f;
					camPos.z = dbNewZValue( obj->getPosZ(), direction, distance );

					Camera * cam = new Camera( currCamera, camPos.x, camPos.y, camPos.z );
					dbSleep(10);

					cameras.push_back( cam );
					// change currCamera to currRobot to be position independent
					cam->setView( viewWidth, viewHeight, startX + (currCamera - 2) * shiftX, startY );
					//cam->lookAt( obj->getPosX(), obj->getPosY() + 20, obj->getPosZ() );
					cam->setRotation( 0, direction, 0 );
					obj->constrainToRotation( cam, "y" );
					obj->constrainToPosition( cam, "xz" );
					//cam->setToImage( currCamera + 20000, viewWidth, viewHeight );

					currCamera++;

					// Create a button so an agent can be selected by clicking on its camera view
					RadioButton * button = new RadioButton( "Models\\Transparent-Button.png", currButton, 
						startX + (currButton - 1) * shiftX, startY, & selectAgent, viewWidth + 6, viewHeight + 6 );

					pcAgentButtons.push_back( button );
					currButton++;

					// Set animations
					obj->addAnimation( Animation::Attack, "Models\\robots\\Android\\H-Android-Attack1.x", 40, true );
					obj->addAnimation( Animation::Die, "Models\\robots\\Android\\H-Android-Die.x", 20 );
					obj->addAnimation( Animation::Idle, "Models\\robots\\Android\\H-Android-Idle.x", 40, true );
					obj->addAnimation( Animation::Impact, "Models\\robots\\Android\\H-Android-Impact.x" );
					obj->addAnimation( Animation::Move, "Models\\robots\\Android\\H-Android-Move.x", 120, true );

					//////////////////////////////////////////////////////////////////////////////////
					newID++;
					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case '@': // Add Assault Trooper start plus empty space
				{
					occupancy( charNum, stringNum ) = 8;

					Agent* obj = new Agent("Models\\GI\\H-GI-Static.x" , newID, goGetEm, occupancy);
					obj->setScale(3000.0f , 3000.0f , 3000.0f);
					obj->applyTexture("Models\\GI\\Gi.dds");
					obj->setPosition(( float ) charNum * 100.0f , 0.0f , ( float ) stringNum * 100.0f);
					world3D.addObject(newID, obj);

					// Set animations
					obj->addAnimation( Animation::Attack, "Models\\GI\\H-GI-Attack1.x", 40, true );
					obj->addAnimation( Animation::Die, "Models\\GI\\H-GI-Die.x" );
					obj->addAnimation( Animation::Idle, "Models\\GI\\H-GI-Idle.x", 40, true );
					obj->addAnimation( Animation::Impact, "Models\\GI\\H-GI-Impact.x" );
					obj->addAnimation( Animation::Move, "Models\\GI\\H-GI-Move.x", 40, true );

					// Allow blending when moving between anims
					// Disables animation if different sequences are appended instead of in the same file >:(
					obj->setInterpolation( 100 );

					newID++;
					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case '*': // Add Thug Baddie start plus empty space
				{
					occupancy( charNum, stringNum ) = 9;

					//TexturedObj* obj = new TexturedObj("Models\\Thug\\L-Thug-Idle.x" , newID);
					Hostile * obj = new Hostile( "Models\\Thug\\L-Thug-Static.x", newID, goGetEm, occupancy );
					obj->setScale(3000.0f , 3000.0f , 3000.0f);
					obj->applyTexture("Models\\Thug\\thug.dds");
					obj->setPosition(( float ) charNum * 100.0f , 0.0f , ( float ) stringNum * 100.0f);

					// TODO this world3d should be removed eventually.
					world3D.addObject(newID, obj);
					myHostiles.insert(myHostiles.end(), obj);

					// Set animations
					obj->addAnimation( Animation::Attack, "Models\\Thug\\L-Thug-Attack1.x", 40, true );
					obj->addAnimation( Animation::Die, "Models\\Thug\\L-Thug-Die.x" );
					obj->addAnimation( Animation::Idle, "Models\\Thug\\L-Thug-Idle.x", 40, true );
					obj->addAnimation( Animation::Impact, "Models\\Thug\\L-Thug-Impact.x" );
					obj->addAnimation( Animation::Move, "Models\\Thug\\L-Thug-Move.x", 40, true );

					// Allow blending when moving between anims
					// Disables animation if different sequences are appended instead of in the same file >:(
					obj->setInterpolation( 100 );


					//dbFixObjectPivot		( baddieCount + 100 );

					newID++;
					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case 'h': // hostages
				{
					occupancy( charNum, stringNum ) = 7;

					//TexturedObj* obj = new TexturedObj("Models\\Thug\\L-Thug-Idle.x" , newID);
					Hostage * obj = new Hostage( "Models\\Thug\\L-Thug-Static.x", newID, goGetEm, occupancy );
					obj->setScale(8000.0f , 8000.0f , 8000.0f);
					obj->applyTexture("Models\\Thug\\thug.dds");
					obj->setPosition(( float ) charNum * 100.0f , 0.0f , ( float ) stringNum * 100.0f);

					// TODO this world3d should be removed eventually.
					world3D.addObject(newID, obj);
					myHostages.insert(myHostages.end(), obj);

					// Set animations
					obj->addAnimation( Animation::Attack, "Models\\Thug\\L-Thug-Attack1.x", 40, true );
					obj->addAnimation( Animation::Die, "Models\\Thug\\L-Thug-Die.x" );
					obj->addAnimation( Animation::Idle, "Models\\Thug\\L-Thug-Idle.x", 40, true );
					obj->addAnimation( Animation::Impact, "Models\\Thug\\L-Thug-Impact.x" );
					obj->addAnimation( Animation::Move, "Models\\Thug\\L-Thug-Move.x", 40, true );

					// Allow blending when moving between anims
					// Disables animation if different sequences are appended instead of in the same file >:(
					obj->setInterpolation( 100 );


					//dbFixObjectPivot		( baddieCount + 100 );

					newID++;
					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;


			case 'r': // RED light plus empty space
				{
					occupancy( charNum, stringNum ) = FALSE;

					dbMakeLight		( lightNum );
					dbSetPointLight ( lightNum , ( float ) charNum * 100 , 100 , ( float ) stringNum * 100 );
					dbColorLight	( lightNum , 0x00AA8888 );
					lightNum++;
					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case 'g': // GREEN light plus empty space
				{
					occupancy( charNum, stringNum ) = '0';

					dbMakeLight		( lightNum );
					dbSetPointLight ( lightNum , ( float ) charNum * 100 , 100 , ( float ) stringNum * 100 );
					dbColorLight	( lightNum , 0x0088AA88 );
					lightNum++;
					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case 'b': // BLUE light plus empty space
				{
					occupancy( charNum, stringNum ) = FALSE;

					dbMakeLight		( lightNum );
					dbSetPointLight ( lightNum , ( float ) charNum * 100 , 100 , ( float ) stringNum * 100 );
					dbColorLight	( lightNum , 0x008888AA );
					lightNum++;
					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case '1':	// Wall block
				{
					dbMakeObjectBox			( objectCount , 100, 100 , 100 );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbTextureObject			( objectCount , 4 );
#ifdef SHADERS
					dbSetBumpMappingOn		( objectCount , 8 );
#endif
					dbSetObjectCollisionOn ( objectCount );
					dbSetObjectCollisionToBoxes ( objectCount);
					//dbShowObjectBounds ( objectCount , 0 );
					//dbFadeObject			( objectCount , 10 );
					//dbScaleObjectTexture	( objectCount , 1 , 2 );
					//dbSetBumpMappingOn		( objectCount , 5 );
					//dbHideObject ( objectCount );
					//dbGhostObjectOn	( objectCount , 0 );
					objectCount++;

					//dbMakeObjectBox			( objectCount , 100, 100 , 100 );
					dbLoadObject ( "Models\\walltop.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 150 , ( float ) stringNum * 100 );
					dbTextureObject			( objectCount , 6 );
					//dbSetObjectCollisionOff ( objectCount );
					//dbScaleObjectTexture	( objectCount , 2 , 2 );
					//dbSetBumpMappingOn		( objectCount , 5 );
					objectCount++;
					addFloor = 0;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 50, 50, 50 );//calculate color id for dark gray
					dbInk ( color, color );//set ink color to dark gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw dark gray representation of door on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case '2':	// Wall block
				{
					dbMakeObjectBox			( objectCount , 100, 100 , 100 );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbTextureObject			( objectCount , 20 );
#ifdef SHADERS
					dbSetBumpMappingOn		( objectCount , 8 );
#endif
					dbSetObjectCollisionOn ( objectCount );
					dbSetObjectCollisionToBoxes ( objectCount);
					dbShowObjectBounds ( objectCount , 0 );
					dbFadeObject			( objectCount , 10 );
					dbScaleObjectTexture	( objectCount , 1 , 2 );
					dbSetBumpMappingOn		( objectCount , 5 );
					dbHideObject ( objectCount );
					dbGhostObjectOn	( objectCount , 0 );
					objectCount++;

					//dbMakeObjectBox			( objectCount , 100, 100 , 100 );
					dbLoadObject ( "Models\\walltop2.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 150 , ( float ) stringNum * 100 );
					dbTextureObject			( objectCount , 6 );
					//dbSetObjectCollisionOff ( objectCount );
					//dbScaleObjectTexture	( objectCount , 2 , 2 );
					//dbSetBumpMappingOn		( objectCount , 5 );
					objectCount++;
					addFloor = 0;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 50, 50, 50 );//calculate color id for dark gray
					dbInk ( color, color );//set ink color to dark gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw dark gray representation of door on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case 'o':	// Pillars
				{
					dbMakeObjectCylinder	( objectCount , 100 );
					dbScaleObject			( objectCount , 50 , 200 , 50 );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 100 , ( float ) stringNum * 100 );
					dbTextureObject			( objectCount , 5 );
					dbScaleObjectTexture	( objectCount , 2 , 4 );
#ifdef SHADERS
					dbSetBumpMappingOn		( objectCount , 9 );
#endif
					objectCount++;
					addFloor = 1;
					shadow = 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 50, 50, 50 );//calculate color id for dark gray
					dbInk ( color, color );//set ink color to dark gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw dark gray representation of door on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case '#':	// Doorway
				{
					occupancy( charNum, stringNum ) = FALSE;

					//dbMakeObjectBox			( objectCount , 100, 100 , 100 );
					dbLoadObject ( "Models\\walltop3.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 150 , ( float ) stringNum * 100 );
					dbTextureObject			( objectCount , 6 );
					dbSetObjectCollisionOff ( objectCount );
					//dbScaleObjectTexture	( objectCount , 2 , 2 );
					//dbSetBumpMappingOn		( objectCount , 5 );
					objectCount++;
					addFloor = 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case 'x':	// Centre Point
				{
					occupancy( charNum, stringNum ) = FALSE;
					addFloor = 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case 's': // south facing door empty space
				{
					occupancy( charNum, stringNum ) = FALSE;

					dbLoadObject			( "Models\\door_frame1.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbScaleObject			( objectCount , 180 , 160 , 130 );
					dbMoveObject			( objectCount ,  -10 );
					dbFadeObject			( objectCount , 200 );
					dbSetObjectCollisionOff	( objectCount );

					door[ doorCount ].type			= 0; // south
					door[ doorCount ].distObj		= ( objectCount );

					objectCount++;

					dbLoadObject			( "Models\\door_1a.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbScaleObject			( objectCount , 100 , 110 , 100 );
					dbMoveObject			( objectCount ,  5 );
					dbSetObjectCollisionOff	( objectCount );

					door[ doorCount ].leftObj		= ( objectCount );
					door[ doorCount ].leftStartX	= dbObjectPositionX ( objectCount );
					door[ doorCount ].leftCurrentX	= dbObjectPositionX ( objectCount );

					objectCount++;

					dbLoadObject			( "Models\\door_1b.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbScaleObject			( objectCount , 100 , 110 , 100 );
					dbMoveObject			( objectCount ,  5 );
					dbSetObjectCollisionOff	( objectCount );

					door[ doorCount ].rightObj		= ( objectCount );
					door[ doorCount ].rightStartX	= dbObjectPositionX ( objectCount );
					door[ doorCount ].rightCurrentX = dbObjectPositionX ( objectCount );

					objectCount++;

					doorCount++;

					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map

					//next section needs to be ran in a seperate loop or will be drawn over by floor
					//or check if there's a color already in it's place when drawing the floor but I dont' no how to do that

					//color = dbRGB ( 255, 255, 255 );//calculate color id for orange
					//dbInk ( color, color );//set ink color to orange
					//dbBox ( 8*charNum , 400 - 8*(stringNum + 2), 8*(charNum + 1), 400 - 8 * (stringNum + 1) );
					////draw white representation of door on mini map
					//dbSetCurrentBitmap(0);//set it back to main map
				} break;

			case 'n': // south facing door empty space
				{
					occupancy( charNum, stringNum ) = FALSE;

					dbLoadObject			( "Models\\door_frame1.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbYRotateObject			( objectCount , 180 );
					dbScaleObject			( objectCount , 180 , 160 , 130 );
					dbMoveObject			( objectCount ,  -10 );
					dbFadeObject			( objectCount , 200 );
					dbSetObjectCollisionOff	( objectCount );

					door[ doorCount ].type			= 1; // south
					door[ doorCount ].distObj		= ( objectCount );

					objectCount++;

					dbLoadObject			( "Models\\door_1a.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbYRotateObject			( objectCount , 180 );
					dbScaleObject			( objectCount , 100 , 110 , 100 );
					dbMoveObject			( objectCount ,  5 );
					dbSetObjectCollisionOff	( objectCount );

					door[ doorCount ].leftObj		= ( objectCount );
					door[ doorCount ].leftStartX	= dbObjectPositionX ( objectCount );
					door[ doorCount ].leftCurrentX	= dbObjectPositionX ( objectCount );

					objectCount++;

					dbLoadObject			( "Models\\door_1b.x" , objectCount );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , 50 , ( float ) stringNum * 100 );
					dbYRotateObject			( objectCount , 180 );
					dbScaleObject			( objectCount , 100 , 110 , 100 );
					dbMoveObject			( objectCount ,  5 );
					dbSetObjectCollisionOff	( objectCount );

					door[ doorCount ].rightObj		= ( objectCount );
					door[ doorCount ].rightStartX	= dbObjectPositionX ( objectCount );
					door[ doorCount ].rightCurrentX = dbObjectPositionX ( objectCount );

					objectCount++;

					doorCount++;

					addFloor	= 1;

					dbSetCurrentBitmap(10);//draw on bitmap
					int color = dbRGB ( 100, 100, 100 );//calculate color id for gray
					dbInk ( color, color );//set ink color to gray
					dbBox ( 8*charNum , 400 - 8*(stringNum + 1), 8*(charNum + 1), 400 - 8 * (stringNum) );
					//draw gray representation of floor on mini map
					color = dbRGB ( 255, 255, 255 );//calculate color id for white
					dbInk ( color, color );//set ink color to white
					dbBox ( 8*charNum , 400 - 8*(stringNum), 8*(charNum + 1), 400 - 8 * (stringNum - 1) );
					//draw gray representation of door on mini map
					dbSetCurrentBitmap(0);//set it back to main map

					//the white representation of the door must be drawn after the loop or else it will be drawn over by the floor
				} break;
			}

			if ( addFloor == 1 ) // if yes then add a floor and ceiling
			{
				// Add the ceiling
				//dbMakeObjectPlane		( objectCount , 100, 100 );
				//dbXRotateObject			( objectCount , 90 );
				//dbPositionObject		( objectCount , ( float ) charNum * 100 , 200 , ( float ) stringNum * 100 );
				//dbTextureObject			( objectCount , 1 );
				//dbSetObjectCollisionOff ( objectCount );
				//objectCount++;

				// Now the floor
				dbMakeObjectPlane		( objectCount , 100, 100 );
				dbXRotateObject			( objectCount , -90 );
				dbPositionObject		( objectCount , ( float ) charNum * 100 , 0 , ( float ) stringNum * 100 );
				dbTextureObject			( objectCount , 1 );
				dbScaleObjectTexture	( objectCount , 2 , 2 );
				dbSetObjectCollisionOff ( objectCount );
				if ( shadow == 1 ) 
				{
					objectCount++;
					dbMakeObjectPlane		( objectCount , 100, 100 );
					dbXRotateObject			( objectCount , -90 );
					dbPositionObject		( objectCount , ( float ) charNum * 100 , .05f , ( float ) stringNum * 100 );
					dbTextureObject			( objectCount , 7 );
					dbSetObjectCollisionOff ( objectCount );
					//dbFadeObject (objectCount , 200 );
				}
				objectCount++;
			}
		}
	}

	//new for loot to draw south facing door (else it'll be drawn over)
	for ( stringNum = 0 ; stringNum < 50 ; stringNum++ )
	{
		for ( charNum = 0 ; charNum < 22 ; charNum++ )
		{
			switch ( czLevel[ stringNum ][ charNum ] )
			{
				//if it's a south facing door
			case 's':
				{
					dbSetCurrentBitmap(10);
					int color = dbRGB ( 255, 255, 255 );//calculate color id for orange
					dbInk ( color, color );//set ink color to orange
					dbBox ( 8*charNum , 400 - 8*(stringNum + 2), 8*(charNum + 1), 400 - 8 * (stringNum + 1) );
					//draw white representation of door on mini map
					dbSetCurrentBitmap(0);//set it back to main map
				}
				break;
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Show the current visual volume
void 
Environment::showVis()
{
	int		iLoop;
	int		visLoop;
	int		colCount=0;
	int		color;

	for ( iLoop = 0 ; iLoop < visCount ; iLoop++)
	{
		switch ( colCount )
		{
		case 0:
			{
				color = 0x00FF0000;
			} break;
		case 1:
			{
				color = 0x0000FF00;
			} break;
		case 2:
			{
				color = 0x000000FF;
			} break;
		case 3:
			{
				color = 0x00FF00FF;
			} break;
		case 4:
			{
				color = 0x00FFFF00;
			} break;
		case 5:
			{
				color = 0x0000FFFF;
			} break;
		}

		colCount++;
		if ( colCount > 5 ) colCount = 0;

		for ( visLoop = vis[iLoop].startObj ; visLoop <= vis[iLoop].endObj ; visLoop++ )
		{
			dbColorObject ( visLoop , color );
		}

	}

}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Move all blocks up 50000
void 
Environment::setupVis()
{
	int iLoop;
	int visLoop;

	for ( iLoop = 0 ; iLoop < visCount ; iLoop++ )
	{
		for ( visLoop = vis[iLoop].startObj ; visLoop < vis[iLoop].endObj + 1 ; visLoop++ )
		{
			dbMoveObjectUp ( visLoop , 50000 );
			//dbExcludeOn ( visLoop );
		}
	}

	currentVis = -1; //to force the vis to update first frame

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// update the visual volume
void 
Environment::updateVis()
{
	int colZ	= (int) ( ( dbCameraPositionZ ( 0 ) - 50 ) / 100.0f ) + 1;
	int	oldVis	= currentVis;
	int iLoop;
	int	visLoop;

	for ( iLoop = 0 ; iLoop < visCount ; iLoop++ )
	{
		if ( colZ >= vis[iLoop].start && colZ <= vis[iLoop].end )
		{
			currentVis = iLoop;
		}
	}

	// Are we in a different vis area?
	if ( currentVis != oldVis )
	{

		// First lets move the new blocks down (if needed)
		for ( iLoop = currentVis -1 ; iLoop < currentVis + 2 ; iLoop++ )
		{
			// does the area need moving down?
			if (iLoop > -1 && iLoop < visCount )
			{
				if ( dbObjectPositionY ( vis[iLoop].startObj ) > 49000 )
				{
					for ( visLoop = vis[iLoop].startObj ; visLoop < vis[iLoop].endObj + 1 ; visLoop++ )
					{
						dbMoveObjectDown ( visLoop , 50000 );	
						//dbExcludeOff ( visLoop );
					}
				}
			}
		}

		// Now lets move the other blocks up (if needed)
		for ( iLoop = 0 ; iLoop < visCount ; iLoop++ )
		{
			if ( iLoop < currentVis -1 || iLoop > currentVis +1 ) // dont move the current vis up
			{
				// does the area need moving up?
				if ( dbObjectPositionY ( vis[iLoop].startObj ) < 49000 )
				{
					for ( visLoop = vis[iLoop].startObj ; visLoop < vis[iLoop].endObj + 1 ; visLoop++ )
					{
						dbMoveObjectUp ( visLoop , 50000 );	
						//dbExcludeOn ( visLoop );
					}
				}
			}
		}

	}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// update the state of the doors 
void 
Environment::updateDoors()
{
	int		iLoop;
	int		iLoop2;
	float	dist;
	bool	open = false;

	for ( iLoop = 0 ; iLoop < doorCount ; iLoop++ )
	{
		open = false;

		// first check if the player is near the door
		if ( door [ iLoop ].type == 0 )
		{
			dist = getDistance ( dbCameraPositionX ( 0 ) , 0 , dbCameraPositionZ ( 0 ) , dbObjectPositionX ( door[ iLoop ].distObj ) , 0 , dbObjectPositionZ ( door[ iLoop ].distObj ) + 50 );
		}
		else
		{
			dist = getDistance ( dbCameraPositionX ( 0 ) , 0 , dbCameraPositionZ ( 0 ) , dbObjectPositionX ( door[ iLoop ].distObj ) , 0 , dbObjectPositionZ ( door[ iLoop ].distObj ) - 50 );
		}

		if ( dist < 150.0f ) open = true;

		//// now check if a baddie is near the door
		//for ( iLoop2 = 0 ; iLoop2 < baddieCount ; iLoop2++ )
		//{
		//	if ( door [ iLoop ].type == 0 )
		//	{
		//		dist = getDistance ( dbObjectPositionX ( baddie [ iLoop2 ].obj ) , 0 , dbObjectPositionZ ( baddie [ iLoop2 ].obj ) , dbObjectPositionX ( door[ iLoop ].distObj ) , 0 , dbObjectPositionZ ( door[ iLoop ].distObj ) + 50 );
		//	}
		//	else
		//	{
		//		dist = getDistance ( dbObjectPositionX ( baddie [ iLoop2 ].obj ) , 0 , dbObjectPositionZ ( baddie [ iLoop2 ].obj ) , dbObjectPositionX ( door[ iLoop ].distObj ) , 0 , dbObjectPositionZ ( door[ iLoop ].distObj ) - 50 );
		//	}

		//	if ( dist < 150.0f ) open = true;
		//}

		if ( open == true )
		{
			if ( dbObjectPositionX ( door[ iLoop ].leftObj ) == door[ iLoop ].leftStartX )
			{
				doorSound = !doorSound;
				if ( doorSound )
				{
					dbStopSound ( 3 );
					dbPlaySound ( 3 , 0 );
				}
				else
				{
					dbStopSound ( 4 );
					dbPlaySound ( 4 , 0 );
				}
			}

			dbMoveObjectLeft	( door[ iLoop ].leftObj , 2 );
			dbMoveObjectRight	( door[ iLoop ].rightObj , 2 );

			if ( door[ iLoop ].type == 0 )
			{
				if ( dbObjectPositionX ( door[ iLoop ].leftObj ) < door[ iLoop ].leftStartX - 100.0f )
				{
					dbPositionObject ( door[ iLoop ].leftObj , door[ iLoop ].leftStartX - 100.0f , dbObjectPositionY ( door[ iLoop ].leftObj )  , dbObjectPositionZ ( door[ iLoop ].leftObj ) );
					dbPositionObject ( door[ iLoop ].rightObj , door[ iLoop ].rightStartX + 100.0f , dbObjectPositionY ( door[ iLoop ].leftObj ) , dbObjectPositionZ ( door[ iLoop ].rightObj ) );
				}
			}
			else
			{
				if ( dbObjectPositionX ( door[ iLoop ].leftObj ) > door[ iLoop ].leftStartX + 100.0f )
				{
					dbPositionObject ( door[ iLoop ].leftObj , door[ iLoop ].leftStartX + 100.0f , dbObjectPositionY ( door[ iLoop ].leftObj ) , dbObjectPositionZ ( door[ iLoop ].leftObj ) );
					dbPositionObject ( door[ iLoop ].rightObj , door[ iLoop ].rightStartX - 100.0f , dbObjectPositionY ( door[ iLoop ].leftObj ) , dbObjectPositionZ ( door[ iLoop ].rightObj ) );
				}
			}

		}
		else
		{
			if ( dbObjectPositionX ( door[ iLoop ].leftObj ) != door[ iLoop ].leftStartX )
			{
				dbMoveObjectRight	( door[ iLoop ].leftObj , 2 );
				dbMoveObjectLeft	( door[ iLoop ].rightObj , 2 );
			}
		}
	}
}
